package cn.kent.high.threadSync;

import java.util.concurrent.CountDownLatch;

/**
 * 问题：在线程池中调用不了线程的join方法
 * 应用： countDownLatch更灵活，对于操作线程同步
 * CountDownLatch 原理解析 CAS操作计数器
 * 和join的区别： join会等待线程结束然后往下走，countDownLatch会等待(await方法)指定线程组执行完了countDown方法后往下走
 *
 * 都是等待线程全部执行完继续往下运行。
 */
public class JoinCountDownLatch {
    private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
                System.out.println("threadOne over!");
            }
        });

        Thread threadTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
                System.out.println("threadTwo over!");
            }
        });

        threadOne.start();
        threadTwo.start();

        System.out.println("wait all threads over.");

        // 等待子线程执行结束返回
        // countDownLatch可以在子线程运行的任何时候让wait方法返回而不一定非要等到子线程执行结束
        // 使用线程池来管理线程时一般都是直接添加Runnable到线程池，这时候就没有办法调用join方法了
        // countDownLatch对比join方法操作线程同步更灵活
        countDownLatch.await(); // 此处若是join方法会一直阻塞主线程直到子线程全部执行完成

        System.out.println("all threads is over.");
    }
}
